package com.iafme.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iafme.config.EmailConfig;
import com.iafme.dto.req.FileReqDTO;
import com.iafme.dto.req.InformationEmailReqDTO;
import com.iafme.dto.req.InformationReqDTO;
import com.iafme.dto.req.UploadFileResDTO;
import com.iafme.dto.res.InformationResDTO;
import com.iafme.mapper.InformationMapper;
import com.iafme.model.Information;
import com.iafme.service.InformationService;
import com.systemframework.exception.ResultException;
import com.systemframework.util.JsoupUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * @author summer
 * @version 1.0
 * @date 2025/3/23 14:11
 */
@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
public class InformationServiceImpl extends ServiceImpl<InformationMapper, Information> implements InformationService {

    @Override
    public Page<InformationResDTO> lists(InformationReqDTO informationReqDTO) {
        Page<Information> page=new Page<>(informationReqDTO.getPageNum(),informationReqDTO.getPageSize());
        LambdaQueryWrapper<Information> lambdaQueryWrapper = Wrappers.lambdaQuery(Information.class)
                .like(StrUtil.isNotEmpty(informationReqDTO.getEmail()), Information::getEmail, informationReqDTO.getEmail())
                .orderByDesc(Information::getCreateTime,Information::getSuccessTime);
        return Convert.convert(new TypeReference<Page<InformationResDTO>>() {
        },this.page(page, lambdaQueryWrapper));
    }
    private final JsoupUtil jsoupUtil;
    private final EmailConfig emailConfig;
    @Override
    public void sendEmail(InformationEmailReqDTO emailReqDTO) {
        String context = jsoupUtil.replaceOssImage(emailReqDTO.getContext());
        List<FileReqDTO> fileReqDTOS=ListUtil.list(true);
        for (UploadFileResDTO<Map<String, Object>> uploadFileResDTO : emailReqDTO.getFileList()) {
            Map<String, Object> response = uploadFileResDTO.getResponse();
            if(CollUtil.isNotEmpty(response) && response.get("code").equals(200)){
                 FileReqDTO fileReqDTO=new FileReqDTO();
                fileReqDTO.setFile(FileUtil.file(Convert.convert(String.class,response.get("data"))));
                fileReqDTO.setName(uploadFileResDTO.getName());
                fileReqDTOS.add(fileReqDTO);
            }
        }

        try {
            emailConfig.sendFile(emailReqDTO.getEmailList().toArray(new String[]{}),context,true,fileReqDTOS,emailReqDTO.getSubject());
            saveSendSuccessEmailNum(emailReqDTO.getEmailList());
            removeFile(fileReqDTOS);
            Information information = this.getById(emailReqDTO.getId());
            if(ObjectUtil.isNotEmpty(information)){
                information.setSuccessTime(LocalDateTime.now());
                this.updateById(information);
            }


        }catch (Exception e){
            saveSendErrorEmailNum(emailReqDTO.getEmailList());
            log.error("failed to send email:{}",e);
            removeFile(fileReqDTOS);
            throw new ResultException(e.getLocalizedMessage());
        }
    }

    private void removeFile(List<FileReqDTO> reqDTOList) {
        if(reqDTOList.size()>0){
            reqDTOList.forEach(reqDTO -> {
                FileUtil.del(reqDTO.getFile());
            });
        }
    }

    private void saveSendSuccessEmailNum(List<String> emailList){
        LambdaQueryWrapper<Information> wrapper = Wrappers.lambdaQuery(Information.class).in(Information::getEmail, emailList);
        List<Information> informationList = this.list(wrapper);
        informationList.forEach(information -> {
            information.setSuccessNum(information.getSuccessNum()+1);
        });
        this.updateBatchById(informationList);
    }

    private void saveSendErrorEmailNum(List<String> emailList){
        LambdaQueryWrapper<Information> wrapper = Wrappers.lambdaQuery(Information.class).in(Information::getEmail, emailList);
        List<Information> informationList = this.list(wrapper);
        informationList.forEach(information -> {
            information.setErrorNum(information.getSuccessNum()+1);
        });
        this.updateBatchById(informationList);
    }
}
